package com.xxadmin.usercenter.config.security.handler;

import com.xxadmin.common.constant.Iconstant;
import com.xxadmin.common.exception.BusinessException;
import com.xxadmin.common.exception.errorcode.ErrorCode;
import com.xxadmin.usercenter.config.security.dto.UserDetailDTO;
import com.xxadmin.usercenter.config.security.service.OauthUserDetailServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * 自定义 认证过程
 *
 * @author:chenming
 * @date:2018/9/6
 */
@Slf4j
@Service
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    @Autowired
    private OauthUserDetailServiceImpl oauthUserDetailService;

    /** 密码 */
    private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();


    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        if(authentication.getCredentials() == null){
            throw new BusinessException(ErrorCode.PASSWORD_NULL,"密码为空");
        }

        String presentedPassword = authentication.getCredentials().toString();
        
        if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
            throw new BusinessException(ErrorCode.PASSWORD_ERROR,"登录密码错误");
        }
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        // 需要对用户在不同渠道下进行校验，输入的用户名为结构为 ： channelCode userName
        if(username.split(" ").length < 2){
            throw new BusinessException(ErrorCode.CHANNEL_CODE_ERROR,"用户名格式有误，请重新输入");
        }
        String channelCode = username.split(" ")[0];
        username = username.split(" ")[1];


        UserDetailDTO userDetail = (UserDetailDTO) oauthUserDetailService.loadUserByUsername(username);
        if(userDetail == null){
            throw new UsernameNotFoundException("该用户不存在，请重新输入");
        }

        if(!channelCode.equals(userDetail.getChannelCode())){
            throw new BusinessException(ErrorCode.CHANNEL_CODE_ERROR,"该用户不属于该渠道下用户");
        }

        if(Iconstant.STATUS_DISABLED.equals(userDetail.getUserStatus())){
            throw new BusinessException(ErrorCode.USER_STATUS_N,"该用户已被禁用");
        }

        return userDetail;
    }

    /**
     * 该方法不能删，否则会报 must be
     * @return
     */
    protected UserDetailsService getUserDetailsService() {
        return oauthUserDetailService;
    }
}
